{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# with 语句是什么?\n",
    "\n",
    "### 有一些任务，可能事先需要设置，事后做清理工作"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    }
   ],
   "source": [
    "import logging\n",
    "\n",
    "file  =  open(\"./test.log\")\n",
    "data = file.readline(10)\n",
    "print(data)\n",
    "file.close()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 以上存在的问题\n",
    " * 可能忘记关机文件句柄\n",
    " * 文件读取数据时，发生异常，并没有进行处理"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 异常处理\n",
    "* 捕捉异常可以使用try/except语句。  \n",
    "     try/except语句用来检测try语句块中的错误，从而让except语句捕获异常信息并处理。\n",
    "> 如果你不想在异常发生时结束你的程序，只需在try里捕获它。\n",
    "* 语法：\n",
    " 以下为简单的try....except...else的语法：\n",
    "```python\n",
    "try:\n",
    "<语句>        #运行别的代码\n",
    "except <名字>：\n",
    "<语句>        #如果在try部份引发了'name'异常\n",
    "except <名字>，<数据>:\n",
    "<语句>        #如果引发了'name'异常，获得附加的数据\n",
    "else:\n",
    "<语句>        #如果没有异常发生\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a的结果为0.5\n",
      "try内第2个运算出错了\n",
      "不管是否异常，最后总要执行的操作\n"
     ]
    }
   ],
   "source": [
    "count = 1\n",
    "try:\n",
    "    a = 1 / 2\n",
    "    print(\"a的结果为{}\".format(a))\n",
    "    count += 1\n",
    "    b = 1 / 0\n",
    "    print(\"b的结果为{}\".format(b))\n",
    "    count += 2\n",
    "    c = 2 / 1\n",
    "    print(c)\n",
    "    print(\"c的结果为{}\".format(c))\n",
    "except:\n",
    "    print(\"try内第{}个运算出错了\".format(count))\n",
    "# except:\n",
    "#     print(\"try内的内容出错了，第一个except已经执行完了\")\n",
    "else:\n",
    "    print(\"try内的内容没有出错\")\n",
    "finally:\n",
    "    print(\"不管是否异常，最后总要执行的操作\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# with...语句相当于try-finally语句的简写，可以替代try-finally的功能。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "进入enter方法\n",
      "with内的语句 enter的返回值\n",
      "进入exit的方法\n",
      "<class 'ZeroDivisionError'> division by zero <traceback object at 0x000001C08D049EC8>\n"
     ]
    }
   ],
   "source": [
    "\n",
    "class Hand():\n",
    "\n",
    "# 先调用__enter__,结束后调用__exit__\n",
    "\n",
    "    def __enter__(self):\n",
    "        print(\"进入enter方法\")\n",
    "        return \"enter的返回值\"\n",
    "\n",
    "    # 执行完相关操作后，调用__exit__方法，如果遇到异常，exit可以获取异常信息\n",
    "    # exit中处理异常，返回true\n",
    "    # 继续执行后面的语句\n",
    "    def __exit__(self,type,value,trace):\n",
    "        print(\"进入exit的方法\")\n",
    "        print(type,value,trace)\n",
    "        return True\n",
    "    \n",
    "hand = Hand()\n",
    "        \n",
    "# as 可以被认为为enter的返回值\n",
    "with hand as content:\n",
    "    print('with内的语句',content)\n",
    "    print(100/0)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2021-04-28 16:27:01,114 [<ipython-input-5-7db6162fec08>:31][INFO] this is information\n",
      "2021-04-28 16:27:01,114 [<ipython-input-5-7db6162fec08>:31][INFO] this is information\n",
      "2021-04-28 16:27:01,114 [<ipython-input-5-7db6162fec08>:31][INFO] this is information\n",
      "2021-04-28 16:27:01,114 [<ipython-input-5-7db6162fec08>:31][INFO] this is information\n",
      "2021-04-28 16:27:01,114 [<ipython-input-5-7db6162fec08>:31][INFO] this is information\n",
      "2021-04-28 16:27:01,118 [<ipython-input-5-7db6162fec08>:32][WARNING] this is warning message\n",
      "2021-04-28 16:27:01,118 [<ipython-input-5-7db6162fec08>:32][WARNING] this is warning message\n",
      "2021-04-28 16:27:01,118 [<ipython-input-5-7db6162fec08>:32][WARNING] this is warning message\n",
      "2021-04-28 16:27:01,118 [<ipython-input-5-7db6162fec08>:32][WARNING] this is warning message\n",
      "2021-04-28 16:27:01,118 [<ipython-input-5-7db6162fec08>:32][WARNING] this is warning message\n",
      "2021-04-28 16:27:01,121 [<ipython-input-5-7db6162fec08>:33][ERROR] this is error message\n",
      "2021-04-28 16:27:01,121 [<ipython-input-5-7db6162fec08>:33][ERROR] this is error message\n",
      "2021-04-28 16:27:01,121 [<ipython-input-5-7db6162fec08>:33][ERROR] this is error message\n",
      "2021-04-28 16:27:01,121 [<ipython-input-5-7db6162fec08>:33][ERROR] this is error message\n",
      "2021-04-28 16:27:01,121 [<ipython-input-5-7db6162fec08>:33][ERROR] this is error message\n",
      "2021-04-28 16:27:01,124 [<ipython-input-5-7db6162fec08>:34][CRITICAL] this is critical message\n",
      "2021-04-28 16:27:01,124 [<ipython-input-5-7db6162fec08>:34][CRITICAL] this is critical message\n",
      "2021-04-28 16:27:01,124 [<ipython-input-5-7db6162fec08>:34][CRITICAL] this is critical message\n",
      "2021-04-28 16:27:01,124 [<ipython-input-5-7db6162fec08>:34][CRITICAL] this is critical message\n",
      "2021-04-28 16:27:01,124 [<ipython-input-5-7db6162fec08>:34][CRITICAL] this is critical message\n",
      "\n"
     ]
    }
   ],
   "source": [
    "def test_with():\n",
    "#     print(\"测试with\")\n",
    "    return True\n",
    "    \n",
    "with open(\"./test.log\",\"r\")  as file:# 打开的文件命名为file，with中自己关闭文件\n",
    "    data = file.read()\n",
    "    print(data)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# rise\n",
    "Python 允许我们在程序中手动设置异常，使用 raise 语句即可"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "输入一个数：g\n",
      "引发异常： ValueError('a 必须是数字')\n"
     ]
    }
   ],
   "source": [
    "try:\n",
    "    a = input(\"输入一个数：\")\n",
    "    #判断用户输入的是否为数字\n",
    "    if(not a.isdigit()):\n",
    "        raise ValueError(\"a 必须是数字\")\n",
    "except ValueError as e:\n",
    "    print(\"引发异常：\",repr(e))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
